package com.pignest.hotel.ui.user;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Button;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Label;
import org.zkoss.zul.Radiogroup;
import org.zkoss.zul.Textbox;

import com.pignest.hotel.beans.Card;
import com.pignest.hotel.beans.Role;
import com.pignest.hotel.beans.User;
import com.pignest.hotel.service.CardService;
import com.pignest.hotel.service.RoleService;
import com.pignest.hotel.service.UserService;
import com.pignest.hotel.spring.Services;
import com.pignest.hotel.system.Global;
import com.pignest.hotel.system.L;
import com.pignest.hotel.util.UIUtils;

public class UserForm extends Grid implements EventListener {
	private static final long serialVersionUID = 3213946332274509708L;
	
	private static final int ACTION_ADD = 1;
	private static final int ACTION_VIEW = 2;
	private static final int ACTION_EDIT = 3;
	
	private Label captionLabel;
	private Checkbox enableCheckbox;
	private Textbox workNumberTextbox;
	private Textbox nameTextbox;
	private Radiogroup genderRadio;
	private Textbox cardNumberTextbox;
	private Textbox phoneTextbox;
	private Textbox remarkTextbox;
	private Component roleContainer;
	
	private Button saveButton;
	private Button resetButton;
	private Button editButton;
	
	private UserService service;
	private User user;
	private int action;

	public UserForm() {
		this.user = null;
		this.action = ACTION_ADD;
		service = Services.getUserService();
		addEventListener("onCreate", this);
	}

	@Override
	public void onEvent(Event event) throws Exception {
		if ("onCreate".equals(event.getName())) {
			captionLabel = (Label)getFellow("captionLabel");
			enableCheckbox = (Checkbox)getFellow("enable");
			workNumberTextbox = (Textbox)getFellow("workNumber");
			nameTextbox = (Textbox)getFellow("name");
			genderRadio = (Radiogroup)getFellow("gender");
			cardNumberTextbox = (Textbox)getFellow("cardNumber");
			phoneTextbox = (Textbox)getFellow("phone");
			remarkTextbox = (Textbox)getFellow("remark");
			roleContainer = getFellow("roleContainer");
			
			saveButton = (Button)getFellow("saveButton");
			resetButton = (Button)getFellow("resetButton");
			editButton = (Button)getFellow("editButton");
		}
	}
	
	public void setUser(User user, int action) {
		this.user = user;
		this.action = action;
		onUserChanged();
	}
	
	public void setUserId(String userId, int action) {
		this.user = Services.getUserService().get(User.class, userId);
		this.action = action;
		onUserChanged();
	}
	
	public void onUserChanged() {
		switch (action) {
		case ACTION_ADD:
			captionLabel.setValue("新增用户");
			enableCheckbox.setChecked(true);
			workNumberTextbox.setValue(null);
			nameTextbox.setValue(null);
			UIUtils.setSelected(genderRadio, Global.getGenders()[0]);
			cardNumberTextbox.setValue(null);
			phoneTextbox.setValue(null);
			remarkTextbox.setValue(null);
			UIUtils.clearSelected(roleContainer);
			break;
		case ACTION_VIEW:
			captionLabel.setValue("查看用户: " + user.getName());
			enableCheckbox.setChecked(user.isEnable());
			workNumberTextbox.setValue(user.getWorkNumber());
			nameTextbox.setValue(user.getName());
			UIUtils.setSelected(genderRadio, user.getGender());
			cardNumberTextbox.setValue(user.getCardNumber());
			phoneTextbox.setValue(user.getPhone());
			remarkTextbox.setValue(user.getRemark());
			setSelectedRoles(user);
			break;
		case ACTION_EDIT:
			captionLabel.setValue("修改用户: " + user.getName());
			enableCheckbox.setChecked(user.isEnable());
			workNumberTextbox.setValue(user.getWorkNumber());
			nameTextbox.setValue(user.getName());
			UIUtils.setSelected(genderRadio, user.getGender());
			cardNumberTextbox.setValue(user.getCardNumber());
			phoneTextbox.setValue(user.getPhone());
			remarkTextbox.setValue(user.getRemark());
			setSelectedRoles(user);
			break;
		default:
			break;
		}
		saveButton.setDisabled(action == ACTION_VIEW);
		resetButton.setDisabled(action == ACTION_VIEW);
		editButton.setVisible(action == ACTION_VIEW);
	}
	
	@SuppressWarnings("unchecked")
	private void setSelectedRoles(User user) {
		RoleService roleService = Services.getRoleService();
		List<Role> roles = roleService.getRolesByUser(user);
		HashSet<String> roleIds = new HashSet<String>();
		for (Role role : roles) {
			roleIds.add(role.getId());
		}
		List<Component> children = roleContainer.getChildren();
		for (Component c : children) {
			if (c instanceof Checkbox) {
				Checkbox ch = (Checkbox)c;
				String roleId = (String)ch.getAttribute("roleId");
				ch.setChecked(roleId != null && roleIds.contains(roleId));
			}
		}
	}
	
	public void onEdit() {
		this.action = ACTION_EDIT;
		saveButton.setDisabled(false);
		resetButton.setDisabled(false);
		editButton.setVisible(false);
	}
	
	public void onSave() {
		String name = nameTextbox.getValue().trim();
		if (StringUtils.isEmpty(name)) {
			UIUtils.alert("姓名不能为空");
			return;
		}
		String workNo = workNumberTextbox.getValue().trim();
		if (StringUtils.isEmpty(workNo)) {
			UIUtils.alert("工号不能为空");
			return;
		}
		boolean edit = action == ACTION_EDIT && user != null;
		if (action == ACTION_ADD || edit && !workNo.equals(user.getWorkNumber())) {
			User u = service.getUserByWorkNo(workNo);
			if (u != null) {
				UIUtils.alert("工号不能重复, 已经有工号为: " + workNo + " 的员工了.");
				return;
			}
		}
		final User user = edit ? this.user : new User();
		boolean enable = enableCheckbox.isChecked();
		String phone = phoneTextbox.getValue();
		String remark = remarkTextbox.getValue();
		user.setEnable(enable);
		user.setName(name);
		user.setWorkNumber(workNo);
		user.setPhone(phone);
		user.setRemark(remark);
		
		final CardService cardService = Services.getCardService();
		final UserService service = Services.getUserService();
		final List<String> roleIds = getRoles(roleContainer);
		final String cardNo = StringUtils.defaultIfEmpty(cardNumberTextbox.getValue(), null);
		final Card card = cardNo == null ? null : cardService.getCardByCardNumber(cardNo);
		if (cardNo != null) {
			if (card == null) {
				UIUtils.alert("系统中没有录入该卡片");
				return;
			} else if (!card.isUsable()) {
				if (!edit || edit && !cardNo.equals(user.getCardNumber())) {
					UIUtils.alert("该卡片已经被占用: " + card.getHolderName2());
					return;
				}
			}
		}
		if (edit) {
			service.executeInTransaction(new Runnable() {
				@Override
				public void run() {
					if (StringUtils.isNotEmpty(user.getCardNumber()) && !user.getCardNumber().equals(cardNo)) {
						cardService.resetCard(user.getCardNumber());
					}
					user.setCardNumber(cardNo);
					service.updateUser(user, roleIds);
					if (cardNo != null) {
						cardService.grantCard(card, user);
					}
				}
			});
			L.update(user);
		} else {
			service.executeInTransaction(new Runnable() {
				@Override
				public void run() {
					user.setCardNumber(cardNo);
					service.insertUser(user, roleIds);
					if (cardNo != null) {
						cardService.grantCard(card, user);
					}
				}
			});
			L.insert(user);
		}
		UIUtils.refresh();
	}
	
	@SuppressWarnings("unchecked")
	private List<String> getRoles(Component c) {
		ArrayList<String> r = new ArrayList<String>();
		List<Component> children = c.getChildren();
		for (Component component : children) {
			if (component instanceof Checkbox) {
				Checkbox ch = (Checkbox)component;
				if (ch.isChecked())
					r.add((String)ch.getAttribute("roleId"));
			}
		}
		return r;
	}
	
	public void onReset() {
		onUserChanged();
	}
	
	public void onReadCard(String cardSerial) {
		if (action != ACTION_ADD && action != ACTION_EDIT)	//add and edit
			return;
		String serial = cardSerial;
		if (serial == null) {
			return;
		}
		Card card = Services.getCardService().getCardBySerialNumber(serial);
		if (card == null) {
			UIUtils.alert("该卡片未在系统中登记, 无法使用");
			return;
		}
		String number = StringUtils.defaultIfEmpty(cardNumberTextbox.getValue(), null);
		if (number != null && number.equals(card.getCardNumber()))
			return;
		if (!card.isUsable()) {
			if (StringUtils.isEmpty(card.getCardNumber())){
				UIUtils.alert("该卡片无法使用, 卡号未设置");
				return;
			}
			UIUtils.alert("该卡片无法使用, 可能已经在使用中(" + card.getHolderName2() + ")");
			return;
		}
		cardNumberTextbox.setValue(card.getCardNumber());
	}
	
	public int getAction2() {
		return action;
	}
}
